home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / p4 / p4-1_2a.lha / p4-1.2a / lib / p4_utils.c < prev    next >
C/C++ Source or Header  |  1992-10-19  |  16KB  |  659 lines

  1. #include "p4.h"
  2. #include "p4_sys.h"
  3.  
  4. char *p4_version()
  5. {
  6.     return(P4_PATCHLEVEL);
  7. }
  8.  
  9. char *p4_machine_type()
  10. {
  11.     return(P4_MACHINE_TYPE);
  12. }
  13.  
  14.  
  15. #if defined(IPSC860)
  16. #define MYNODE mynode
  17. #endif
  18. #if defined(CM5)
  19. #define MYNODE CMMD_self_address
  20. #endif
  21.  
  22. int p4_initenv(argc, argv)
  23. int *argc;
  24. char **argv;
  25. {
  26.     int i, rc;
  27.     P4BOOL am_slave = FALSE;
  28.  
  29.     sprintf(whoami, "xm_%d", getpid());
  30.  
  31.     for (i = 0; i < *argc; i++)
  32.     if (strcmp(argv[i], "-amp4slave") == 0)
  33.         am_slave = TRUE;
  34.  
  35. #   if defined(CM5)
  36.     CMMD_fset_io_mode( stdin,  CMMD_independent );
  37.     CMMD_fset_io_mode( stdout, CMMD_independent );
  38.     CMMD_fset_io_mode( stderr, CMMD_independent );
  39.     if (MYNODE() != 0)
  40.         am_slave = TRUE;
  41. #   endif
  42.  
  43.     p4_local  = NULL;
  44.     p4_global = NULL;
  45.  
  46.     if (am_slave)
  47.     {
  48. #       if defined(IPSC860)  ||  defined(CM5)
  49.         if (MYNODE() == 0)
  50.     {
  51. #           if defined(IPSC860_SOCKETS)  ||  defined(CM5_SOCKETS)
  52.         rc = rm_start(argc, argv);
  53. #           endif
  54.     }
  55.     else
  56.     {
  57.         rc = ns_start(argc, argv);
  58.     }
  59. #       else
  60.     rc = rm_start(argc, argv);
  61. #       endif
  62.     ALOG_SETUP(p4_local->my_id,ALOG_TRUNCATE);
  63.     }
  64.     else
  65.     {
  66.     rc = bm_start(argc, argv);
  67.         ALOG_MASTER(0,ALOG_TRUNCATE);
  68.         ALOG_DEFINE(BEGIN_USER,"beg_user","");
  69.         ALOG_DEFINE(END_USER,"end_user","");
  70.         ALOG_DEFINE(BEGIN_SEND,"beg_send","");
  71.         ALOG_DEFINE(END_SEND,"end_send","");
  72.         ALOG_DEFINE(BEGIN_RECV,"beg_recv","");
  73.         ALOG_DEFINE(END_RECV,"end_recv","");
  74.         ALOG_DEFINE(BEGIN_WAIT,"beg_wait","");
  75.         ALOG_DEFINE(END_WAIT,"end_wait","");
  76.     }
  77.     ALOG_LOG(p4_local->my_id,BEGIN_USER,0,"");
  78.     return (rc);
  79. }
  80.  
  81. char *p4_shmalloc(n)
  82. int n;
  83. {
  84.     char *rc;
  85.  
  86.     if ((rc = MD_shmalloc(n)) == NULL)
  87.     p4_dprintf("p4_shmalloc returning NULL; request = %d bytes\n",n);
  88.     return (rc);
  89. }
  90.  
  91. P4VOID p4_shfree(p)
  92. char *p;
  93. {
  94.     MD_shfree(p);
  95. }
  96.  
  97. int p4_num_cluster_ids()
  98. {
  99.     return (p4_global->local_slave_count + 1);
  100. }
  101.  
  102. int p4_num_total_ids()
  103. {
  104.     return (p4_global->num_in_proctable);
  105. }
  106.  
  107. int p4_num_total_slaves()
  108. {
  109.     return (p4_global->num_in_proctable - 1);
  110. }
  111.  
  112.  
  113. P4VOID p4_global_barrier(type)
  114. int type;
  115. {
  116.     double dummy[1];
  117.  
  118.     p4_global_op(type, (char *) dummy, 1, sizeof(double), p4_dbl_sum_op, P4DBL);
  119. }
  120.  
  121.  
  122. P4VOID p4_get_cluster_masters(numids, ids)
  123. int *numids, ids[];
  124. {
  125.     int node;
  126.  
  127.     ids[0] = 0;
  128.     *numids = 1;
  129.     for (node = 1; node < p4_global->num_in_proctable; node++)
  130.     {
  131.     if (p4_global->proctable[node].slave_idx != 0)
  132.         continue;
  133.     ids[(*numids)++] = node;
  134.     }
  135. }
  136.  
  137.  
  138. P4VOID p4_get_cluster_ids(start, end)
  139. int *start;
  140. int *end;
  141. {
  142.  
  143.     *start = p4_global->low_cluster_id;
  144.     *end = p4_global->hi_cluster_id;
  145. }
  146.  
  147. /* This is used to figure out the local id of the calling process by
  148.  * indexing into the proctable until you find a hostname and a unix id
  149.  * that are the same as yours.
  150.  */
  151. int p4_get_my_id_from_proc()
  152. {
  153.     int i, my_unix_id;
  154.     struct proc_info *pi;
  155.     struct hostent *myhp, *pghp;
  156.  
  157. #   if (defined(IPSC860)  &&  !defined(IPSC860_SOCKETS))  ||  \
  158.        (defined(CM5)      &&  !defined(CM5_SOCKETS))
  159.     return(MYNODE());
  160. #   else
  161.     my_unix_id = getpid();
  162.     if (p4_local->my_id == LISTENER_ID)
  163.     return (LISTENER_ID);
  164.     myhp = gethostbyname_p4(p4_global->my_host_name);
  165.  
  166.     for (pi = p4_global->proctable, i = 0; i < p4_global->num_in_proctable; i++, pi++)
  167.     {
  168.     if (pi->unix_id == my_unix_id)
  169.     {
  170.         if (strcmp(pi->host_name, p4_global->my_host_name) == 0)
  171.         {
  172.         return (i);
  173.         }
  174.         else
  175.         {
  176.         pghp = gethostbyname_p4(pi->host_name);
  177.         if (bcmp(myhp->h_addr, pghp->h_addr, myhp->h_length) == 0)
  178.         {
  179.             return (i);
  180.         }
  181.         }
  182.     }
  183.     }
  184.     p4_dprintf("process not in process table; my_unix_id = %d my_host=%s\n",
  185.            getpid(), p4_global->my_host_name);
  186.     p4_dprintf("Probable cause:  local slave on uniprocessor without shared memory\n");
  187.     p4_dprintf("Probable fix:  ensure only one process on %s\n",p4_global->my_host_name);
  188.     p4_dprintf("(on master process this means 'local 0' in the procgroup file)\n");
  189.     p4_dprintf("You can also remake p4 with SYSV_IPC set in the OPTIONS file\n");
  190.     p4_error("p4_get_my_id_from_proc",0);
  191. #   endif
  192. }
  193.  
  194. int p4_get_my_id()
  195. {
  196.     return (p4_local->my_id);
  197. }
  198.  
  199. int p4_get_my_cluster_id()
  200. {
  201. #   if (defined(IPSC860)  &&  !defined(IPSC860_SOCKETS))  ||  \
  202.        (defined(CM5)      &&  !defined(CM5_SOCKETS))
  203.     return(MYNODE());
  204. #   else
  205.     if (p4_local->my_id == LISTENER_ID)
  206.     return (LISTENER_ID);
  207.     else
  208.     return (p4_global->proctable[p4_local->my_id].slave_idx);
  209. #   endif
  210. }
  211.  
  212. P4BOOL p4_am_i_cluster_master()
  213. {
  214.     if (p4_local->my_id == LISTENER_ID)
  215.     return (0);
  216.     else
  217.     return (p4_global->proctable[p4_local->my_id].slave_idx == 0);
  218. }
  219.  
  220. P4BOOL in_same_cluster(i, j)
  221. int i, j;
  222. {
  223.     return (p4_global->proctable[i].group_id ==
  224.         p4_global->proctable[j].group_id);
  225. }
  226.  
  227. P4VOID p4_cluster_shmem_sync(cluster_shmem)
  228. P4VOID **cluster_shmem;
  229. {
  230.     int myid = p4_get_my_cluster_id();
  231.  
  232.     if (myid == 0)  /* cluster master */
  233.     p4_global->cluster_shmem = *cluster_shmem;
  234.     p4_barrier(&(p4_global->cluster_barrier),p4_num_cluster_ids());
  235.     if (myid != 0)
  236.     *cluster_shmem = p4_global->cluster_shmem;
  237. }
  238.  
  239. #if defined(USE_XX_SHMALLOC)
  240. /* This is not machine dependent code but is only used on some machines */
  241.  
  242. /*
  243.   Memory management routines from ANSI K&R C, modified to manage
  244.   a single block of shared memory.
  245.   Have stripped out all the usage monitoring to keep it simple.
  246.  
  247.   To initialize a piece of shared memory:
  248.     xx_init_shmalloc(char *memory, unsigned nbytes)
  249.  
  250.   Then call xx_shmalloc() and xx_shfree() as usual.
  251. */
  252.  
  253. #define LOG_ALIGN 4
  254. #define ALIGNMENT (1 << LOG_ALIGN)
  255.  
  256. /* ALIGNMENT is assumed below to be bigger than sizeof(p4_lock_t) +
  257.    sizeof(Header *), so do not reduce LOG_ALIGN below 4 */
  258.  
  259. union header
  260. {
  261.     struct
  262.     {
  263.     union header *ptr;    /* next block if on free list */
  264.     unsigned size;        /* size of this block */
  265.     } s;
  266.     char align[ALIGNMENT];    /* Align to ALIGNMENT byte boundary */
  267. };
  268.  
  269. typedef union header Header;
  270.  
  271. static Header **freep;        /* pointer to pointer to start of free list */
  272. static p4_lock_t *shmem_lock;    /* Pointer to lock */
  273.  
  274. P4VOID xx_init_shmalloc(memory, nbytes)
  275. char *memory;
  276. unsigned nbytes;
  277. /*
  278.   memory points to a region of shared memory nbytes long.
  279.   initialize the data structures needed to manage this memory
  280. */
  281. {
  282.     int nunits = nbytes >> LOG_ALIGN;
  283.     Header *region = (Header *) memory;
  284.  
  285.     /* Quick check that things are OK */
  286.  
  287.     if (ALIGNMENT != sizeof(Header) ||
  288.     ALIGNMENT < (sizeof(Header *) + sizeof(p4_lock_t)))
  289.     p4_error("xx_init_shmem: Alignment is wrong", ALIGNMENT);
  290.  
  291.     if (!region)
  292.     p4_error("xx_init_shmem: Passed null pointer", 0);
  293.  
  294.     if (nunits < 2)
  295.     p4_error("xx_init_shmem: Initial region is ridiculously small",
  296.          (int) nbytes);
  297.  
  298.     /*
  299.      * Shared memory region is structured as follows
  300.      * 
  301.      * 1) (Header *) freep ... free list pointer 2) (p4_lock_t) shmem_lock ...
  302.      * space to hold lock 3) padding up to alignment boundary 4) First header
  303.      * of free list
  304.      */
  305.  
  306.     freep = (Header **) region;    /* Free space pointer in first block  */
  307.     shmem_lock = (p4_lock_t *) (freep + 1);    /* Lock still in first block */
  308.     (region + 1)->s.ptr = *freep = region + 1;    /* Data in rest */
  309.     (region + 1)->s.size = nunits - 1;    /* One header consumed already */
  310.  
  311. #   ifdef SYSV_IPC
  312.     shmem_lock->semid = sysv_semid0;
  313.     shmem_lock->semnum = 0;
  314. #   else
  315.     p4_lock_init(shmem_lock);                /* Initialize the lock */
  316. #   endif
  317.  
  318. }
  319.  
  320. char *xx_shmalloc(nbytes)
  321. unsigned nbytes;
  322. {
  323.     Header *p, *prevp;
  324.     char *address = (char *) NULL;
  325.     unsigned nunits;
  326.  
  327.     /* Force entire routine to be single threaded */
  328.     (P4VOID) p4_lock(shmem_lock);
  329.  
  330.     nunits = ((nbytes + sizeof(Header) - 1) >> LOG_ALIGN) + 1;
  331.  
  332.     prevp = *freep;
  333.     for (p = prevp->s.ptr;; prevp = p, p = p->s.ptr)
  334.     {
  335.     if (p->s.size >= nunits)
  336.     {            /* Big enuf */
  337.         if (p->s.size == nunits)    /* exact fit */
  338.         prevp->s.ptr = p->s.ptr;
  339.         else
  340.         {            /* allocate tail end */
  341.         p->s.size -= nunits;
  342.         p += p->s.size;
  343.         p->s.size = nunits;
  344.         }
  345.         *freep = prevp;
  346.         address = (char *) (p + 1);
  347.         break;
  348.     }
  349.     if (p == *freep)
  350.     {            /* wrapped around the free list ... no fit
  351.                  * found */
  352.         address = (char *) NULL;
  353.         break;
  354.     }
  355.     }
  356.  
  357.     /* End critical region */
  358.     (P4VOID) p4_unlock(shmem_lock);
  359.  
  360.     if (address == NULL)
  361.     p4_dprintf("xx_shmalloc: returning NULL; requested %d bytes\n",nbytes);
  362.     return address;
  363. }
  364.  
  365. P4VOID xx_shfree(ap)
  366. char *ap;
  367. {
  368.     Header *bp, *p;
  369.  
  370.     /* Begin critical region */
  371.     (P4VOID) p4_lock(shmem_lock);
  372.  
  373.     if (!ap)
  374.     return;            /* Do nothing with NULL pointers */
  375.  
  376.     bp = (Header *) ap - 1;    /* Point to block header */
  377.  
  378.     for (p = *freep; !(bp > p && bp < p->s.ptr); p = p->s.ptr)
  379.     if (p >= p->s.ptr && (bp > p || bp < p->s.ptr))
  380.         break;        /* Freed block at start of end of arena */
  381.  
  382.     if (bp + bp->s.size == p->s.ptr)
  383.     {                /* join to upper neighbour */
  384.     bp->s.size += p->s.ptr->s.size;
  385.     bp->s.ptr = p->s.ptr->s.ptr;
  386.     }
  387.     else
  388.     bp->s.ptr = p->s.ptr;
  389.  
  390.     if (p + p->s.size == bp)
  391.     {                /* Join to lower neighbour */
  392.     p->s.size += bp->s.size;
  393.     p->s.ptr = bp->s.ptr;
  394.     }
  395.     else
  396.     p->s.ptr = bp;
  397.  
  398.     *freep = p;
  399.  
  400.     /* End critical region */
  401.     (P4VOID) p4_unlock(shmem_lock);
  402. }
  403. #endif
  404.  
  405. P4VOID get_pipe(end_1, end_2)
  406. int *end_1;
  407. int *end_2;
  408. {
  409.     int p[2];
  410.  
  411. #   if defined(IPSC860)  ||  defined(CM5)
  412.     p4_dprintf("WARNING: get_pipe: socketpair assumed unavailable on this machine\n");
  413.     return;
  414. #   else
  415.     if (socketpair(AF_UNIX, SOCK_STREAM, 0, p) < 0)
  416.     p4_error("get_pipe: socketpair failed ", -1);
  417.     *end_1 = p[0];
  418.     *end_2 = p[1];
  419. #   endif
  420. }
  421.  
  422. P4VOID setup_conntab()
  423. {
  424.     int i, my_id;
  425.  
  426.     p4_dprintfl(60, "setup_conntab: myid=%d, switch_port=%d, app_id=%s\n",
  427.         p4_local->my_id,
  428.         p4_global->proctable[p4_local->my_id].switch_port,
  429.         p4_global->application_id);
  430.     p4_local->conntab = (struct connection *)
  431.     p4_malloc(p4_global->num_in_proctable * sizeof(struct connection));
  432.     my_id = p4_get_my_id();
  433.  
  434.     for (i = 0; i < p4_global->num_in_proctable; i++)
  435.     {
  436.     if (i == my_id)
  437.     {
  438.         p4_local->conntab[i].type = CONN_ME;
  439.         p4_local->conntab[i].port = 0;
  440.     }
  441.     else if (in_same_cluster(i, my_id))
  442.     {
  443.         p4_local->conntab[i].type = CONN_LOCAL;
  444. #           if defined(IPSC860) || defined(CM5)
  445.         p4_local->conntab[i].port = MYNODE() + i - p4_local->my_id;
  446. #           endif
  447. #           if defined(TCMP)
  448.         p4_local->conntab[i].port = i - p4_global->low_cluster_id;
  449. #           endif
  450.     }
  451.     else if ((p4_global->proctable[my_id].switch_port != -1) &&
  452.          (p4_global->proctable[i].switch_port != -1) &&
  453.          (p4_global->proctable[my_id].switch_port !=
  454.           p4_global->proctable[i].switch_port))
  455.     {
  456.         p4_local->conntab[i].type = CONN_REMOTE_SWITCH;
  457.         p4_local->conntab[i].switch_port = p4_global->proctable[i].switch_port;
  458.     }
  459.     else
  460.     {
  461.         p4_local->conntab[i].type = CONN_REMOTE_NON_EST;
  462.         p4_local->conntab[i].port = p4_global->proctable[i].port;
  463.     }
  464.     }
  465.     p4_dprintfl(60, "conntab after setup_conntab:\n");
  466.     dump_conntab(60);
  467. }
  468.  
  469. #ifdef SYSV_IPC
  470. P4VOID remove_sysv_ipc()
  471. {
  472.     int i;
  473.     struct p4_global_data *g = p4_global;
  474.  
  475.     /* ignore -1 return codes below due to multiple processes cleaning
  476.        up the same sysv stuff; commented out "if" used to make sure
  477.        that only the cluster master cleaned up in each cluster
  478.     */
  479.     /* if (p4_local != NULL  &&  p4_get_my_cluster_id() != 0) return; */
  480.  
  481.     semctl(g->sysv_semid[0],0,IPC_RMID,0);  /* delete initial set */
  482.     if (sysv_shmid[0] == -1)
  483.     return;
  484.     for (i=0; i < sysv_num_shmids; i++)
  485.         shmctl(sysv_shmid[i],IPC_RMID,0);
  486.     if (g == NULL)
  487.         return;
  488.     for (i=1; i < g->sysv_num_semids; i++)  /* delete other sets */
  489.     {
  490.     semctl(g->sysv_semid[i],0,IPC_RMID,0);
  491.     }
  492. }
  493. #endif
  494.  
  495. int p4_wait_for_end()
  496. {
  497.     int status;
  498.     int i, n_forked_slaves, pid;
  499.     struct slave_listener_msg msg;
  500.  
  501.     ALOG_LOG(p4_local->my_id,END_USER,0,"");
  502.     ALOG_OUTPUT;
  503.  
  504.     /* Wait for all forked processes except listener to die */
  505.     p4_dprintfl(90, "enter wait_for_end nfpid=%d\n",p4_global->n_forked_pids);
  506.     if (p4_local->listener_fd == (-1))
  507.         n_forked_slaves = p4_global->n_forked_pids;
  508.     else
  509.         n_forked_slaves = p4_global->n_forked_pids - 1;
  510.     for (i = 0; i < n_forked_slaves; i++)
  511.     {
  512.     pid = wait(&status);
  513.     p4_dprintfl(90, "detected that proc %d died \n", pid);
  514.     }
  515.  
  516. #   ifdef CAN_DO_SOCKET_MSGS
  517.     /* Tell the listener to die and wait for him to do so */
  518.     if (p4_local->listener_fd != (-1))
  519.     {
  520.     p4_dprintfl(90, "tell listener to die listpid=%d fd=%d\n",
  521.             p4_global->listener_pid, p4_local->listener_fd);
  522.     msg.type = p4_i_to_n(DIE);
  523.     msg.from = p4_i_to_n(p4_get_my_id());
  524.     net_send(p4_local->listener_fd, &msg, sizeof(msg), FALSE);
  525.     pid = wait(&status);
  526.     p4_dprintfl(90, "detected that proc %d died \n", pid);
  527.     }
  528. #   endif
  529.  
  530. #   ifdef SYSV_IPC
  531.     remove_sysv_ipc();
  532. #   endif
  533.  
  534.     if (p4_get_my_id())
  535.         p4_dprintfl(20,"process exiting\n");
  536.     p4_dprintfl(90, "exit wait_for_end \n");
  537.     return (0);
  538. }
  539.  
  540.  
  541. /* static variables private to fork_p4 and zap_p4_processes */
  542. static int n_pids = 0;
  543. static int pid_list[P4_MAXPROCS];
  544.  
  545. int fork_p4()
  546. /*
  547.   Wrapper round fork for sole purpose of keeping track of pids so 
  548.   that can signal error conditions.  See zap_p4_processes.
  549. */
  550. {
  551.     int pid;
  552.  
  553. #   if defined(IPSC860)  ||  defined(CM5)
  554.     p4_error("p4_fork: nodes cannot fork processes",0);    
  555. #   else
  556.     if (p4_global->n_forked_pids >= P4_MAXPROCS)
  557.     p4_error("forking too many local processes; max = ", P4_MAXPROCS);
  558.     p4_global->n_forked_pids++;
  559.  
  560.     fflush(stdout);
  561.     pid = fork();
  562.  
  563.     if (pid > 0)
  564.     {
  565.     /* Parent process */
  566.     pid_list[n_pids++] = pid;
  567.     }
  568.     else if (pid == 0)
  569.     {
  570.     /* Child process */
  571.     pid_list[n_pids++] = getppid();
  572.     }
  573.     else
  574.     p4_error("fork_p4: fork failed", pid);
  575. #   endif
  576.  
  577.     return pid;
  578. }
  579.  
  580. P4VOID zap_p4_processes()
  581. {
  582.     int n;
  583.     
  584.     if (p4_global == NULL)
  585.         return;
  586.     n = p4_global->n_forked_pids;
  587.     while (n--)
  588.     {
  589.     kill(pid_list[n], SIGINT);
  590.     }
  591. }
  592.  
  593. P4VOID get_qualified_hostname(str)
  594. char *str;
  595. {
  596. #   if (defined(IPSC860)  &&  !defined(IPSC860_SOCKETS))  ||  \
  597.        (defined(CM5)      &&  !defined(CM5_SOCKETS))
  598.     strcpy(str,"cube_node");
  599. #else
  600.     if (*str == '\0')
  601.         gethostname(str, 100);
  602.     if (*local_domain != '\0'  &&  !index(str,'.'))
  603.     {
  604.     strcat(str,".");
  605.     strcat(str,local_domain);
  606.     }
  607. #endif
  608. }
  609.  
  610.  
  611. int getswport(hostname)
  612. char *hostname;
  613. {
  614.     char local_host[256];
  615.  
  616. #ifdef CAN_DO_SWITCH_MSGS
  617.     if (strcmp(hostname, "local") == 0)
  618.     {
  619.     local_host[0] = '\0';
  620.     get_qualified_hostname(local_host);
  621.     return getswport(local_host);
  622.     }
  623.     if (strcmp(hostname, "hurley") == 0)
  624.     return 1;
  625.     if (strcmp(hostname, "hurley.tcg.anl.gov") == 0)
  626.     return 1;
  627.     if (strcmp(hostname, "hurley.mcs.anl.gov") == 0)
  628.     return 1;
  629.     if (strcmp(hostname, "campus.mcs.anl.gov") == 0)
  630.     return 2;
  631.     if (strcmp(hostname,"mpp1") == 0)
  632.       return 3;
  633.     if (strcmp(hostname,"mpp2") == 0)
  634.       return 28;
  635.     if (strcmp(hostname,"mpp3") == 0)
  636.       return 6;
  637.     if (strcmp(hostname,"mpp4") == 0)
  638.       return 7;
  639.     if (strcmp(hostname,"mpp7") == 0)
  640.       return 14;
  641.     if (strcmp(hostname,"mpp8") == 0)
  642.       return 25;
  643.     if (strcmp(hostname,"mpp9") == 0)
  644.       return 20;
  645.     if (strcmp(hostname,"mpp10") == 0)
  646.       return 11;
  647. #endif
  648.  
  649.     return -1;
  650. }
  651.  
  652. P4BOOL same_data_representation(id1,id2)
  653. {
  654.     struct proc_info *p1 = &(p4_global->proctable[id1]);
  655.     struct proc_info *p2 = &(p4_global->proctable[id2]);
  656.  
  657.     return (data_representation(p1->machine_type) == data_representation(p2->machine_type));
  658. }
  659.